use std::ffi::OsStr;

use stencil_mir::MirModule;

pub(super) use super::errors::Error;
pub(super) use super::util::CodeBuffer;

/// Short compact ID for a code generator backend.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CodegenId {
    Python,
}

impl CodegenId {
    /// Parses it from a "name string" that can be declared explicitly.
    pub fn from_name_str(s: &str) -> Option<Self> {
        let cg = match s {
            "python" | "py" | "py3" => Self::Python,
            _ => return None,
        };
        Some(cg)
    }

    /// Tries to parse it from a file extension.
    pub fn from_ext(ext: &OsStr) -> Option<Self> {
        let s = ext.to_str()?;
        let cg = match s {
            "py" => Self::Python,
            _ => return None,
        };
        Some(cg)
    }
}

/// Codegen backend system.
pub trait CodegenBackend {
    /// The toplevel module type for the language's IR.
    type LangIrModule;

    /// Gets the indent string used to init the dest buffer.
    fn get_indent(&self) -> String;

    /// Gets the comment prefix string.
    fn get_comment_prefix(&self) -> String;

    /// Gets the comment suffix string, if the codegen uses them.
    fn get_comment_suffix(&self) -> Option<String>;

    /// Converts the common IR to the lang IR.
    fn convert_mir_to_lir(&self, mir_mod: &MirModule) -> Result<Self::LangIrModule, Error>;

    /// Generates code from the lang IR.
    fn generate_lang_ir(
        &self,
        lang_module: &Self::LangIrModule,
        buf: &mut CodeBuffer,
    ) -> Result<(), Error>;
}
